package com.hmall.gateway.filter;

import cn.hutool.core.text.AntPathMatcher;
import com.hmall.gateway.config.AuthProperties;
import com.hmall.gateway.config.JwtProperties;
import com.hmall.gateway.utils.JwtTool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

// 启用配置属性绑定，使得JwtProperties和AuthProperties能够从配置文件中读取配置
@EnableConfigurationProperties({JwtProperties.class, AuthProperties.class})
@Component
public class AuthGlobalFilter implements GlobalFilter {
    // 注入认证相关配置属性
    @Autowired
    private AuthProperties authProperties;
    // 注入JWT工具类，用于解析和验证token
    @Autowired
    private JwtTool jwtTool;

    // 路径匹配器，用于匹配请求路径是否符合排除规则
    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    /**
     * 过滤器核心方法，处理每个经过网关的请求
     * @param exchange 服务网络交换机，包含请求和响应信息
     * @param chain 过滤器链，用于继续执行后续过滤器
     * @return Mono<Void> 异步处理结果
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取当前请求和响应对象
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();

        // 获取请求的URI路径
        String uri = request.getPath().toString();
        // 判断当前请求是否在排除路径中，如果在排除路径中则直接放行
        if (isExclude(uri)){
            return chain.filter(exchange);
        }
        // 从请求头中获取Authorization字段，即JWT token
        String token = request.getHeaders().getFirst("Authorization");
        Long userId = null;
        try {
            // 使用JWT工具解析token，获取用户ID
            userId = jwtTool.parseToken(token);
        }catch (Exception e){
            // 如果解析token出现异常，返回401未授权状态码和错误信息
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
            return response.writeWith(Mono.just(response.bufferFactory().wrap("参数错误".getBytes())));
        }

        // 将用户ID转换为字符串格式
        String userInfo = userId.toString();
        // 将用户ID信息添加到请求头中，供后续服务使用
        exchange.mutate().request(r -> r.header("userInfo", userInfo));

        // 继续执行过滤器链中的下一个过滤器
        return chain.filter(exchange);

    }
    
    /**
     * 判断请求路径是否在排除列表中
     * @param uri 请求的URI路径
     * @return boolean 如果在排除列表中返回true，否则返回false
     */
    private boolean isExclude(String uri){
        // 使用stream流遍历排除路径列表，判断是否有路径匹配当前请求URI
        return authProperties.getExcludePaths().stream().anyMatch(p -> antPathMatcher.match(p, uri));
    }
}